package source.Control
{
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.ByteArray;
    import flash.filesystem.File;
    import flash.filesystem.FileStream;
    import flash.filesystem.FileMode;
    import net.flashpunk.Entity;
    import net.flashpunk.FP;
    import net.flashpunk.graphics.Image;
    import net.flashpunk.graphics.Tilemap;
    import net.flashpunk.utils.Input;
    import net.flashpunk.utils.Key;
    import net.flashpunk.World;
    import source.Assets;
    import source.Global;
    import source.Objetos.*;
    import source.Solidos.*;
	import mx.utils.ObjectUtil;

	public class Juego extends  World {
		
		public var reset:int = 180; //timer so that reset level doesn't happen right away...
		private var pantalla:Pantalla;
		
        /**
         * Juego
         * Constructor
         */
        public function Juego(_pantallaACargar:uint = 1) {
            //cargamos la primera pantalla:
            removeAll();
            Global.idPantallaActual = _pantallaACargar; //la pantalla a cargar será, por defecto, el segundo elemento del array (el primero es la pantalla de error)
			pantalla = new Pantalla(this);
            pantalla.cargarPantalla();
            
            //configuramos las teclas:
            Input.define("Dch", Key.RIGHT);
            Input.define("Ab", Key.DOWN);
            Input.define("Izq", Key.LEFT);
            Input.define("Arr", Key.UP);
            Input.define("Accion", Key.A, Key.ENTER);
            Input.define("Salto", Key.S);
            Input.define("Disparo", Key.D);
            Input.define("Agacharse", Key.CONTROL);
            Input.define("GolpeDescendente", Key.DOWN);
            Input.define("Salvar", Key.DOWN);
            Input.define("Suicidio", Key.K);
            Input.define("Mapa", Key.M);
            Input.define("Pausa", Key.ESCAPE);
            Input.define("ConsolaDebug", Key.F12);
        }
        
        /**
         * begin
         * Es llamado cuando este world pasa a ser el world activo del engine
         */
		override public function begin():void {
            Global.enJuego = true;
		}
		
        /**
         * update
         * Es llamado cada frame
         */
		override public function update():void {
			if (!Global.juegoParalizado) super.update(); //solo actualizamos si el juego no está paralizado
			
			//Si debemos respawnear el pj se encontrará paralizado, y hasta que el timer no termine no se cargará la pantalla
			if (Global.respawn && Global.pj.muerto) {
				reset -= 1; //decrementamos el timer
				if (reset == 0) {
					pantalla.siguientePantalla(); //recomenzamos la pantalla
					reset = 180; //reseteamos nuestro timer
				}
			}
			
			//Si hemos atravesado una puerta o salido por un borde...
			else if (Global.salirPantalla_porPuerta || Global.salirPantalla_porTeletransporte)
				pantalla.siguientePantalla();
            else {
                if (Global.pj == collideLine("PJ", 0, -1, FP.width, -1)) {
                    Global.salirPantalla_porBorde = true; //indicamos que hemos de salir del área
                    Global.salirPantalla_porBorde_Lado = "n"; //indicamos por qué lado saldremos del área
                    pantalla.siguientePantalla();
                }
                else if (Global.pj == collideLine("PJ", FP.width + 1, 0, FP.width + 1, FP.height)) {
                    Global.salirPantalla_porBorde = true; //indicamos que hemos de salir del área
                    Global.salirPantalla_porBorde_Lado = "e"; //indicamos por qué lado saldremos del área
                    pantalla.siguientePantalla();
                }
                else if (Global.pj == collideLine("PJ", 0, FP.height + 1, FP.width, FP.height + 1)) {
                    Global.salirPantalla_porBorde = true; //indicamos que hemos de salir del área
                    Global.salirPantalla_porBorde_Lado = "s"; //indicamos por qué lado saldremos del área
                    pantalla.siguientePantalla();
                }
                else if (Global.pj == collideLine("PJ", -1, 0, -1, FP.height)) {
                    Global.salirPantalla_porBorde = true; //indicamos que hemos de salir del área
                    Global.salirPantalla_porBorde_Lado = "o"; //indicamos por qué lado saldremos del área
                    pantalla.siguientePantalla();
                }
            }
            
            if (Input.pressed("Pausa")) {
                FP.buffer.applyFilter(FP.buffer, new Rectangle(0, 0, FP.width, FP.height), new Point, new BlurFilter()); //emborronamos la pantalla
                Global.bufferPantalla = FP.screen.capture(); //capturamos la pantalla, ya emborronada, para ponerla como fondo del menú de pausa
                FP.world = Global.menu; //cambiamos al world menú
            }
		}
		

		
		/**
         * restaurarPJ
		 * Restaura las propiedades del PJ al cambiar de pantalla, respawnear o cargar la partida
		 */
		public function restaurarPJ():void {
			//propiedades elementales:
			Global.pj.speed.x              = Global.pjTemp.speed.x;
			Global.pj.speed.y              = Global.pjTemp.speed.y;
			Global.pj.direction            = Global.pjTemp.direction;
			Global.pj.doblesaltodisponible = Global.pjTemp.doblesaltodisponible;
			Global.pj.direction            = Global.pjTemp.direction;
			
			//powerups:
			Global.pj.correr           = Global.pjTemp.correr;
			Global.pj.dobleSalto       = Global.pjTemp.dobleSalto;
			Global.pj.caminaragachado  = Global.pjTemp.caminaragachado;
			Global.pj.disparar         = Global.pjTemp.disparar;
			Global.pj.nadar            = Global.pjTemp.nadar;
			Global.pj.empujar          = Global.pjTemp.empujar;
			Global.pj.golpeDescendente = Global.pjTemp.golpeDescendente;	
		}
        
		/**
         * slotEnUso
		 * Devolverá si el slot está en uso o no
		 */
		public static function slotEnUso(slot:uint):Boolean {
            var enUso:Boolean = false;
            var file:File = new File(File.applicationDirectory.nativePath + "/saves/slot" + slot + ".gs"); //manejador del fichero
            var fileStream:FileStream = new FileStream(); //manejador de la lectura/escritura del fichero
            
            if (file.exists) {
                fileStream.open(file, FileMode.READ); //abrimos el fichero para lectura
                var xml:XML = new XML(fileStream.readMultiByte(file.size, File.systemCharset));
                enUso = xml.@enUso == "true";
                fileStream.close(); //cerramos el fichero
            }
            else {
                //CREAR AQUÍ UN FICHERO NUEVO, EN BASE A 'Assets.SLOT_VACIO'
                enUso = false;
            }
            return enUso;
		}
        
        /**
         * cargarPartida
		 * Carga del slot que se esté usando los datos de la partida
		 */
		public static function cargarPartida():void {
            Global.pjTemp = new PJ(); //creamos al PJ temporal para utilizarlo en la carga de partidas guardadas
            Global.respawn = true;
            
            var file:File = new File(File.applicationDirectory.nativePath + "/saves/slot" + Global.slot + ".gs"); //manejador del fichero
            var fileStream:FileStream = new FileStream(); //manejador de la lectura/escritura del fichero
            
            if (file.exists) {
                fileStream.open(file, FileMode.READ); //abrimos el fichero para lectura
                
                var str:String = fileStream.readMultiByte(file.size, File.systemCharset); //con str echaremos un vistazo "por encima" a los "datos en bruto"
                var xml:XML = new XML(str);                                               //con xml buscaremos datos específicos, ya leyendo como formato XML
                
                //Establecemos la pantalla en la que se encuentra el PJ:
                Global.savepointDestino = int(xml.localizacion.@id);
                
                //Establecemos los poderes que posee el PJ:
                Global.pjTemp.correr = (xml.poderes.@c == "true");
                Global.pjTemp.dobleSalto = (xml.poderes.@ds == "true");
                Global.pjTemp.disparar = (xml.poderes.@d  == "true");
                Global.pjTemp.nadar = (xml.poderes.@n  == "true");
                Global.pjTemp.empujar = (xml.poderes.@e  == "true");
                Global.pjTemp.golpeDescendente = (xml.poderes.@gd == "true");
                
                fileStream.close(); //cerramos el fichero
            }
		}
        
		/**
         * guardarPartida
		 * Guarda los datos de la partida en el slot que se esté usando
		 */
		public static function guardarPartida():void {
            var file:File = new File(File.applicationDirectory.nativePath + "/saves/slot" + Global.slot + ".gs"); //manejador del fichero
            var fileStream:FileStream = new FileStream(); //manejador de la lectura/escritura del fichero
            
            if (file.exists) {
                //Abrimos el fichero para escritura:
                fileStream.open(file, FileMode.WRITE);
            
                //Cargamos el objeto XML correspondiente a un slot vacío:
                var slotVacio:ByteArray = new Assets.SLOT_VACIO;
                var xml:XML = new XML(slotVacio.readUTFBytes(slotVacio.length));
                
                //Modificamos el objeto XML correspondiente a un slot vacío con los datos de la partida:
                xml.@num = Global.slot.toString();
                xml.@enUso = "true";
                xml.localizacion.@id = Global.idPantallaActual.toString();
                xml.poderes.@c  = Global.pj.correr.toString();
                xml.poderes.@ds = Global.pj.dobleSalto.toString();
                xml.poderes.@d  = Global.pj.disparar.toString();
                xml.poderes.@n  = Global.pj.nadar.toString();
                xml.poderes.@e  = Global.pj.empujar.toString();
                xml.poderes.@gd = Global.pj.golpeDescendente.toString();
                
                //Escribimos en el fichero y lo cerramos:
                fileStream.writeMultiByte(xml.toString(), File.systemCharset);
                fileStream.close();
            }
		}
	}
}











//